import SSHConfig from 'ssh2-promise/lib/sshConfig'
import { SSH, SSHUtil, SSHResultType } from '@xtail/ssh'
import { send2FocusedWin } from '../utils'

const sshs: Record<string, SSH> = {}

export const SSHSessionOpen = async (channel: string, config: SSHConfig) => {
  // 防止出现同一个 channel 两次不同连接使用不同的连接配置，两者之间发送冲突，后面的连接依旧使用之前的配置
  // 所以每次都创建新的连接实例，如果旧实例连接仍然存在则尝试关闭会话断开连接；旧实例关闭失败与否，都直接覆盖
  if (sshs[channel] && sshs[channel].isConnected) await SSHSessionClose(channel)
  const ssh = new SSH(config)
  sshs[channel] = ssh
  let res = await ssh.connect()
  if (!res.success) return SSHUtil.genResultBySSHRes(res, false)
  res = await ssh.sessionOpen(
    (data) => send2FocusedWin(channel, data, false),
    () => send2FocusedWin(channel, `与服务器主机建立的 SSH 会话关闭`, true)
  )
  return SSHUtil.genResultBySSHRes(res, false)
}

export type SSHSessionOpenType = typeof SSHSessionOpen

export const SSHSessionExec = async (channel: string, cmd: string) => {
  const ssh = sshs[channel]
  if (!ssh || !ssh.isConnected || !ssh.isSessionOpen)
    return ResultUtil.genFailResult('与服务器还未建立 SSH 会话')
  const res = await ssh.sessionExec(cmd)
  return SSHUtil.genResultBySSHRes(res, false)
}

export type SSHSessionExecType = typeof SSHSessionExec

export const SSHSessionClose = async (channel: string) => {
  const ssh = sshs[channel]
  if (!ssh || !ssh.isConnected) {
    Reflect.deleteProperty(sshs, channel)
    return ResultUtil.genSuccessResult('已关闭与服务器的 SSH 连接')
  }
  let res: SSHResultType
  if (ssh.isSessionOpen) {
    res = await ssh.sessionClose()
    if (!res.success) return SSHUtil.genResultBySSHRes(res, false)
  }
  res = await ssh.close()
  if (res.success) Reflect.deleteProperty(sshs, channel)
  return SSHUtil.genResultBySSHRes(res, false)
}

export type SSHSessionCloseType = typeof SSHSessionClose
